# 作者： 李泉志
# 2025年01月13日13时32分秒
# 2947029073@qq.com

"""
sort常用场景
    sort函数是list列表中的函数，而sorted可以对list或者iterator进行排序
    sort和sorted的比较
        用sort函数对列表排序时会影响列表本身，而 sorted不会
        sorted(iterable，key，reverse)
            参数：iterable可以是list或者iterator；
            key是带一个参数的函数；（等价于 C/C++的 compare）
            reverse为False或者True；
    相比于sort()，sorted()使用的范围更为广泛，两者的函数形式分别如下：
        sorted(iterable[[, key[, reverse]]])
        s.sort([[, key[, reverse]]])
    这两个方法有以下3个共同的参数：
        key是带一个参数的函数，用来为每个元素提取比较值，默认为 None（即直接比较每个元素）。
        reverse表示排序结果是否反转

基本排序 Sorting Basics
    进行一个简单的升序排列直接调用 sorted()函数，函数将会返回一个排序后的列表：
        >>> sorted([5, 2, 3, 1, 4])
        [1, 2, 3, 4, 5]
    sorted函数不会改变原有的list，而是返回一个新的排好序的list
    如果想使用就地排序，也就是改变原list的内容，那么可以使用 list.sort()的方法，这个方法的返回值是None。
    另一个区别是，list.sort()方法只是list也就是列表类型的方法，只可以在列表类型上调用。
    而sorted方法则是可以接受任何可迭代对象。
key 函数 Key Functions
    list.sort()和 sorted()函数都有一个key参数，可以用来指定一个函数来确定排序的一个优先级。
    比如，根据大小写的优先级进行排序：key=str.lower
    key参数的值应该是一个函数，这个函数接受一个参数然后返回以一个key，这个key就被用作进行排序。
    这个方法很高效，因为对于每一个输入的记录只需要调用一次key函数。

operator 库函数自定义排序（ Operator Module Functions）
    前面我们看到的利用 key-function 来自定义排序，同时Python也可以通过operator库来自定义排序，
    而且通常这种方法更好理解并且效率更高。
    operator库提供了itemgetter(), attrgetter(), and a methodcaller()三个函数
    itemgetter()函数可以用来获取一个list的元素，attrgetter()函数可以用来获取一个类的属性，

升序和降序 Ascending and Descending
    list.sort()和 sorted()都有一个 boolean类型的reverse参数，可以用来指定升序和降序排列，
    默认为 false，也就是升序排序，如果需要降序排列，则需将 reverse参数指定为 true。
"""


# 比较规则
def change_lower(str_name: str):
    return str_name.lower()  # 转换为小写


if __name__ == '__main__':
    # s = sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
    # print(s)  # Output: [1, 2, 3, 4, 5]
    my_list = "This is a test string from Andrew".split()
    print(my_list)
    print(sorted(my_list, key=change_lower))

    my_list.sort(key=change_lower)
    print(my_list)

    student_tuples = [
        ('john', 'A', 15),
        ('jane', 'B', 12),
        ('dave', 'B', 10),
    ]
    # lambda表达式就是匿名函数
    print(sorted(student_tuples, key=lambda student: student[2]))  # 按第三个元素排序
    print('-' * 50)


    class Student:

        def __init__(self, name, grade, age):
            self.name = name
            self.grade = grade
            self.age = age

        def __repr__(self):
            """
            相对于__str__方法，__repr__方法可以返回一非字符串类型
            """
            return repr((self.name, self.grade, self.age))


    student = Student('john', 'A', 15)
    student_objects = [
        Student('john', 'A', 15),
        Student('jane', 'B', 12),
        Student('dave', 'B', 10),
    ]
    print(sorted(student_objects, key=lambda student: student.name))
    print('-' * 50)

    from operator import itemgetter, attrgetter

    print('使用operator库自定义排序')
    print(sorted(student_tuples, key=itemgetter(2)))
    # 按第三个元素排序,也可以用键值‘age’
    print(sorted(student_objects, key=attrgetter('age')))

    print(sorted(student_tuples, key=itemgetter(1, 2)))
    print(sorted(student_tuples, key=lambda x: (x[1], x[2])))

    print(sorted(student_tuples, key=lambda x: (x[1], -x[2])))  # 按第二列升序第三列降序排序
    print(sorted(student_tuples, key=lambda x: (x[1], -x[2]), reverse=True))
    print('-' * 50)


    # 字典中混合 list 排序
    mydict = {'Li': ['M', 7],
              'Zhang': ['E', 2],
              'Wang': ['P', 3],
              'Du': ['C', 2],
              'Ma': ['C', 9],
              'Zhe': ['H', 7]}
    print(sorted(mydict.items(), key=lambda v: v[1][1]))  # 按第数字排序
